import Random from "./random";
import SparkMD5 from 'spark-md5'
const CHARS = 'ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz2345678';
const CHARS2 = 'abcdefhijkmnprstwxyz';    /****默认去掉了容易混淆的字符oOLl,9gq,Vv,Uu,I1****/
class Utils {
    isNull(value) {
        if ((!value || typeof (value) == "undefined") && value != 0) {
            return true
        }
        return false
    }
    randomString(len, rand?: Random) {
        len = len || 32;
        /****默认去掉了容易混淆的字符oOLl,9gq,Vv,Uu,I1****/
        var maxPos = CHARS.length;
        var pwd = '';
        for (var i = 0; i < len; i++) {
            if (rand) {
                pwd += CHARS.charAt(Math.floor(rand.floor(maxPos)));
            } else {
                pwd += CHARS.charAt(Math.floor(Math.random() * maxPos));
            }

        }
        return pwd;
    }
    randomRegisterString(len) {
        len = len || 32;
        var pwd = '';
        for (var i = 0; i < 4; i++) {
            pwd += CHARS2.charAt(Math.floor(Math.random() * CHARS2.length));
        }
        var char2s = '123456789';
        for (var i = 0; i < len; i++) {
            pwd += char2s.charAt(Math.floor(Math.random() * char2s.length));
        }
        return pwd;
    }
    randomRegisterPwd(len) {
        len = len || 8;
        var char2s = '123456789';
        var pwd = ""
        for (var i = 0; i < len; i++) {
            pwd += char2s.charAt(Math.floor(Math.random() * char2s.length));
        }
        return pwd;
    }
    getOneFromArray<T>(array: T[], rand: Random): T {
        if (rand) {
            return array[Math.floor(rand.floor(array.length))]
        } else {
            return array[Math.floor(Math.random() * array.length)]
        }
    }

    isSameDay(date_1: number, date_2: number) {
        let dateOne = new Date(date_1).setHours(0, 0, 0, 0)
        let dateTwo = new Date(date_2).setHours(0, 0, 0, 0)
        return (dateOne == dateTwo)
    }

    getIndexByRandomArray(array: number[], rand: Random): number {
        let total = 0
        array.forEach((value, i) => {
            total += value
        })
        let r = rand.intn(total)
        let j = 0
        while (j < array.length) {
            if (r <= array[j]) {
                return j
            } else {
                r -= array[j]
            }
            j += 1
        }
        return j
    }
    sleep(timeout: number, cb?: (number) => void): Promise<any> {
        return new Promise(async resolve => {
            let timerID = window.setTimeout(resolve, timeout);
            cb && cb(timerID)
        })
    }
    floor = (value: number, len?: number) => {
        if (len == null) {
            len = 1
        }
        return Number(value.toFixed(len))
    }
    //将字符串中的非数字字符去掉并去掉前导的'0' 返回一个数字
    getNumberFromString(value: string) {
        value = value.replace(/[^\d]/g, '')//移除非数字字符
        let oldLen = value.length
        value = value.replace(/^0+/, ''); // 移除前导零
        if (value.length === 0 && oldLen > 0)
            value = '0'
        return Number(value)
    }
    //根据角色等级 属性成长值 计算当前角色该属性值   第三个参数设置返回值是否取整
    getAttriValue(value: any[], lv: number): number {
        let v = 0
        if (value[1] == 0)
            v = value[0]
        else if (value[1] == 1) {
            v = Math.floor(value[0] * Math.pow(2, Math.floor(lv / 10)) * (lv % 10 * 0.1 + 1))
        }
        else if (value[1] == 2) {
            v = value[0] + Math.floor(lv / 10) * 2
        }
        else if (value[1] == 3) {
            v = value[0] + Math.floor(lv / 10) * 4
        }
        //console.log('计算属性:等级=' + lv + '/初始值=' + value[0] + '/成长值=' + value[1] + '/属性=' + v)
        return v;
    }

    //获取随机值  用于根据概率数组获得随机装备品质   参数 values[10,100,200,300], coe:1000  10/1000概率获得最高品级 一共5个品级
    getRandomValue(values: any[], coe: number, rand: Random): number {
        let max = values.length + 1
        let sj = rand.intn(coe)
        let j = max
        while (j > 1) {
            if (sj <= values[max - j]) {
                break
            } else {
                sj -= values[max - j]
            }
            j--
        }
        return j
    }


    getIncValue(values: any[], lvl: number, floor: boolean = false): number {
        let v = 0
        if (values[2]) {
            let value2 = values[2]
            let value4 = 1
            if (values[3]) {
                value4 = Math.pow(1 + values[3] / 100, lvl)
            }
            v = (values[0] + values[1] * lvl + value2 * lvl * (lvl + 1) / 2) * value4

        } else {
            v = (values[0] + values[1] * lvl)
        }
        if (values[4] == 'int') {
            return Math.floor(v)
        } else if (values[4] == 'floor') {
            return utils.floor(v, 3)
        }
        if (floor) {
            return utils.floor(v, 3)
        } else {
            return Math.floor(v)
        }
    }
    getIncValue2(values: any[], lvl: number, maxLvl: number = 0): number {
        let v = 0
        let base = values[0]
        let lvlInc = values[1]
        let lvlAddInc = values[2]
        let lvlInterval = values[3] || 1
        let lvlcoe = Math.floor(lvl / lvlInterval)
        let lvlcoeMax = Math.floor(maxLvl / lvlInterval)
        let lvlother = lvl % lvlInterval
        v = Math.floor(base + lvlInc * lvl)
        for (let i = 0; i < lvlcoe; i++) {
            if (maxLvl !== 0 && i > lvlcoeMax) {
                v += lvlAddInc * lvlcoeMax * lvlInterval
            } else {
                v += lvlAddInc * i * lvlInterval
            }
        }
        if (maxLvl !== 0 && lvlcoe > lvlcoeMax) {
            v += lvlAddInc * lvlcoeMax * lvlother
        } else {
            v += lvlAddInc * lvlcoe * lvlother
        }
        return Math.floor(v)
    }
    getRandomNumber(min: number, max: number, rand?: Random): number {
        if (rand) {
            if (max < min) {
                return Math.floor(rand.floor(min - max + 1) + max)
            } else {
                return Math.floor(rand.floor(max - min + 1) + min)
            }
        } else {
            if (max < min) {
                return Math.floor(Math.random() * (min - max + 1) + max)
            } else {
                return Math.floor(Math.random() * (max - min + 1) + min)
            }
        }
    }
    getRandomNumberFloor(min: number, max: number, rand?: Random): number {
        if (rand) {
            if (max < min) {
                return rand.floor(min - max + 1) + max
            } else {
                return rand.floor(max - min + 1) + min
            }
        } else {
            if (max < min) {
                return Math.random() * (min - max + 1) + max
            } else {
                return Math.random() * (max - min + 1) + min
            }
        }
    }
    getRandomArrayNoRepeat<T>(array: T[], num: number, rand: Random): T[] {
        let arrayCopy = array.slice(0)
        let length = arrayCopy.length
        var k = []
        if (num > length) {
            num = length
        }
        for (var i = 0; i < num; i++) {
            var l = Math.floor(rand.floor(length))
            length = length - 1
            k.push(arrayCopy[l])
            arrayCopy[l] = arrayCopy[length]
        }
        return k
    }
    getOneFromArrayAndRemove<T>(array: T[], rand?: Random): T {
        if (rand) {
            let index = Math.floor(rand.floor(array.length))
            let value = array[index]
            array.splice(index, 1)
            return value
        } else {
            let index = Math.floor(Math.random() * array.length)
            let value = array[index]
            array.splice(index, 1)
            return value
        }
    }

    addRandomByPer(value: number, per: number, rand?: Random, numberType: string = 'int'): number {
        if (numberType == 'int') {
            let max = Math.floor(value)
            if (max <= 0) {
                max = 1
            }
            let min = Math.floor(value * per / 100)
            if (min <= 0) {
                min = 1
            }
            return this.getRandomNumber(min, max, rand)
        } else {
            let max = value
            if (max <= 0) {
                max = 0
            }
            let min = value * per / 100
            if (min <= 0) {
                min = 0
            }
            let n = this.getRandomNumberFloor(min, max, rand)
            if (n > max) {
                n = max
            }
            n = Number(n.toFixed(1))
            return n
        }
    }
    getDuration(duration: number, durationPer: number[]): number[] {
        let d: number[] = []
        for (let i = 0; i < durationPer.length; i++) {
            let p1 = durationPer[i]
            if (i > 0) {
                let p2 = durationPer[i - 1]
                d.push(duration * p1 / 100 - duration * p2 / 100)
            } else {
                d.push(duration * p1 / 100)
            }
        }
        return d
    }
    getPerByAttri(name: string) {
        if (name.indexOf('Per') !== -1 || name == 'critHurt' || name == 'crit' || name == 'realHurt' || name == 'antiRealHurt'
            || name == 'addSkillHurt' || name == 'reduceCure' || name == 'addAttackHurt' || name == 'reduceSkillHurt' || name == 'reduceAttackHurt'
            || name == 'hit' || name == 'dodge' || name == 'antiCrit' || name == 'antiCritHurt' || name == 'reduceHurt') {
            return '%'
        } else {
            return ''
        }
    }
    //根据属性类别保留小数
    getValueByAttri(value: number, name: string) {
        if (name.indexOf('Per') !== -1 || name == 'critHurt' || name == 'crit' || name == 'realHurt' || name == 'antiRealHurt'
            || name == 'addSkillHurt' || name == 'reduceCure' || name == 'addAttackHurt' || name == 'reduceSkillHurt' || name == 'reduceAttackHurt'
            || name == 'hit' || name == 'dodge' || name == 'antiCrit' || name == 'antiCritHurt' || name == 'reduceHurt') {
            return Number(value.toFixed(1))
        } else {
            return Number(value.toFixed())
        }
    }
    getNumberText = (value) => {
        if (value > 10000 && value < 10000000) {
            return utils.floor(value / 10000, 1) + '万'
        } else if (value >= 10000000 && value < 100000000) {
            return utils.floor(value / 10000, 0) + '万'
        } else if (value >= 100000000) {
            return utils.floor(value / 100000000, 0) + '亿'
        } else {
            return value
        }
    }
    getNumberText2 = (value) => {
        if (value >= 1000 && value <= 10000) {
            return utils.floor(value / 1000, 1) + 'k'
        } else if (value > 10000 && value < 10000000) {
            return utils.floor(value / 10000, 1) + 'm'
        } else if (value >= 10000000 && value < 100000000) {
            return utils.floor(value / 10000, 0) + 'm'
        } else if (value >= 100000000) {
            return utils.floor(value / 100000000, 0) + 'e'
        } else {
            return value
        }
    }
    checkFile = async (): Promise<any> => {
        let _mainjs = window.localStorage.getItem("mainjs")
        if (window["platform"] == 'ios') {
            return new Promise(resolve => {
                window["resolveLocalFileSystemURL"](window["cordova"].file.tempDirectory,
                    function (fs) {
                        fs.getDirectory(
                            "js", {
                            create: false
                        },
                            function (fsdirectory) {
                                let directoryReader = fsdirectory.createReader();
                                directoryReader.readEntries((entries) => {
                                    let filesAmount = entries.length
                                    for (let i = 0; i < filesAmount; i++) {
                                        let fileEntry = entries[i]
                                        if (fileEntry.name == _mainjs) {
                                            fileEntry.file((file) => {
                                                var reader = new FileReader();
                                                reader.onloadend = function (e) {

                                                    resolve(SparkMD5.hash(this.result))
                                                };
                                                reader.readAsText(file);
                                            }, () => { });
                                        }
                                    }

                                });
                            })
                    })
            })
        } else {
            return new Promise(resolve => {
                window["resolveLocalFileSystemURL"](window["cordova"].file.externalDataDirectory,
                    function (fs) {
                        fs.getDirectory(
                            "js", {
                            create: false
                        },
                            function (fsdirectory) {
                                let directoryReader = fsdirectory.createReader();
                                directoryReader.readEntries((entries) => {
                                    let filesAmount = entries.length
                                    for (let i = 0; i < filesAmount; i++) {
                                        let fileEntry = entries[i]

                                        if (fileEntry.name == _mainjs) {
                                            fileEntry.file((file) => {
                                                var reader = new FileReader();
                                                reader.onloadend = function (e) {

                                                    resolve(SparkMD5.hash(this.result))
                                                };
                                                reader.readAsText(file);
                                            }, () => { });
                                        }
                                    }

                                });
                            })
                    })
            })
        }

    }
}

let utils = new Utils()
export default utils
